<?php

declare(strict_types=1);

namespace common\override;

use app\admin\cache\FileUploadConfigCache;
use app\admin\enum\EnableStatus;
use app\admin\model\FileUploadConfig;
use Tinywan\Storage\Storage as BaseStorage;

class Storage extends BaseStorage
{
    /**
     * 根据存储类型获取磁盘实例
     * @param string|null $name 存储配置名称
     * @param bool $_is_file_upload 是否为文件上传
     * @param array $extra 额外配置
     * @return mixed
     */
    public static function disk(string $name = null, bool $_is_file_upload = true, array $extra = []): mixed
    {
        if ($name) {
            $fileConfig = FileUploadConfig::where('storage_type', $name)->first();
        } else {
            $fileConfig = FileUploadConfigCache::get();
            if ($fileConfig === null) {
                $fileConfig = FileUploadConfig::where('status', EnableStatus::ENABLE->value)->first();
                FileUploadConfigCache::set($fileConfig);
            }
        }
        $config = self::buildStorageConfig($fileConfig);
        return new $config['adapter'](array_merge($config, ['_is_file_upload' => $_is_file_upload], $extra));
    }

    protected static function buildStorageConfig(FileUploadConfig $fileConfig): array
    {
        $dirname = DIRECTORY_SEPARATOR . $fileConfig->config['dirname'] . DIRECTORY_SEPARATOR . date('Ymd');
        // 构建基础配置
        $baseConfig = [
            'single_limit' => $fileConfig->single_limit,
            'total_limit' => $fileConfig->total_limit,
            'nums' => $fileConfig->nums,
            'include' => $fileConfig->include ?? [],
            'exclude' => $fileConfig->exclude ?? [],
        ];
        // 根据存储类型构建特定配置
        $specificConfig = match ($fileConfig->storage_type) {
            'local' => [
                'adapter' => \Tinywan\Storage\Adapter\LocalAdapter::class,
                'root' => public_path(),
                'dirname' => $dirname,
                'domain' => $fileConfig->config['domain'],
                'uri' => $fileConfig->config['uri'],
                'algo' => $fileConfig->config['algo'],
            ],
            'oss' => [
                'adapter' => \Tinywan\Storage\Adapter\OssAdapter::class,
                'accessKeyId' => $fileConfig->config['accessKeyId'],
                'accessKeySecret' => $fileConfig->config['accessKeySecret'],
                'bucket' => $fileConfig->config['bucket'],
                'dirname' => $dirname,
                'domain' => $fileConfig->config['domain'],
                'endpoint' => $fileConfig->config['endpoint'],
                'algo' => $fileConfig->config['algo'],
            ],
            'cos' => [
                'adapter' => \Tinywan\Storage\Adapter\CosAdapter::class,
                'secretId' => $fileConfig->config['secretId'],
                'secretKey' => $fileConfig->config['secretKey'],
                'bucket' => $fileConfig->config['bucket'],
                'dirname' => $dirname,
                'domain' => $fileConfig->config['domain'],
                'region' => $fileConfig->config['region'],
            ],
            'qiniu' => [
                'adapter' => \Tinywan\Storage\Adapter\QiniuAdapter::class,
                'accessKey' => $fileConfig->config['accessKey'],
                'secretKey' => $fileConfig->config['secretKey'],
                'bucket' => $fileConfig->config['bucket'],
                'dirname' => $dirname,
                'domain' => $fileConfig->config['domain'],
            ],
            's3' => [
                'adapter' => \Tinywan\Storage\Adapter\S3Adapter::class,
                'key' => $fileConfig->config['key'],
                'secret' => $fileConfig->config['secret'],
                'bucket' => $fileConfig->config['bucket'],
                'dirname' => $dirname,
                'domain' => $fileConfig->config['domain'],
                'region' => $fileConfig->config['region'],
                'version' => $fileConfig->config['version'],
                'use_path_style_endpoint' => $fileConfig->config['use_path_style_endpoint'],
                'endpoint' => $fileConfig->config['endpoint'],
                'acl' => $fileConfig->config['acl'],
            ],
        };
        return array_merge($baseConfig, $specificConfig);
    }
}